﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Brainee.Search;
using Brainee.Optimization;

namespace Brainee.Examples.Optimization
{
  public class EightQueens : IOptimizationProblem
  {
#region States

    public class State : IState
    {
      /// <summary>
      /// Current state of the problem
      /// </summary>
      /// <remarks>
      /// The value given by _state[i] is the row of the queen located in the i'th column.
      /// </remarks>
      private byte[] _state = new byte [8];

      public State (params byte [] rows)
      {
        if (rows.Length != 8)
          throw new ArgumentOutOfRangeException ();

        rows.CopyTo (_state, 0);
      }

      public State (State s, byte col, byte row)
        : this(s._state)
      {
        _state [col] = row;
      }

      public byte this[int index]
      {
        get { return _state [index]; }
      }
    }

#endregion
#region IOptimizationProblem implementation

    public IState InitialState
    {
      get;
      set;
    }

    public IEnumerable<IState> Successors (IState state)
    {
      State s = state as State;

      for (byte col = 0; col < 8; col++)
      {
        for (byte row = 0; row < 8; row++)
        {
          if (row != s [col])
          {
            yield return new State (s, col, row);
          }
        }
      }
    }

    Random _random = new Random ((int)DateTime.Now.Ticks);

    public IState RandomSuccessor (IState state)
    {
      State s = state as State;

      while (true)
      {
        byte col = (byte)_random.Next (8);
        byte row = (byte)_random.Next (8);
        if (row != s [col])
        {
          return new State (s, col, row);
        }
      }
    }

    public double Evaluate (IState state)
    {
      State s = state as State;

      int value = 0;
      for (int col = 0; col < 8; col++)
      {
        for (int offset = 1; offset < 8 - col; offset++)
        {
          if ((s [col + offset] == s [col] - offset)
           || (s [col + offset] == s [col])
           || (s [col + offset] == s [col] + offset))
          {
            value ++;
          }
        }
      }

      return -value;
    }

#endregion
  }
}
